#include <string.h>
#include <assert.h>
#include <vector>
#include <iostream>

#include <cstdlib>
#include <cstdio>


#include "qm.h"

using namespace std;

typedef struct {
    int center;
    int type;
    int contr;
} basis_shell_t;

typedef struct {
    int shell;
    int type;
} basis_func_t;

typedef struct {
    int K,KC;
    double *a, **C;
}basis_contr_t;

typedef struct {
    Geom_t geom;
    vector<basis_contr_t> contrs;
    vector<basis_shell_t> shells;
    vector<basis_func_t> funcs;
} basis_t;


typedef int Basis_t;
static vector<basis_t*> datav;

int Basis_create(Basis_t *basis) {
     
   for(int i = 0; i < datav.size(); ++i) {
	if(!datav[i]) {
	    datav[i] = new basis_t;
	    *basis = i;
	    return 0;
	}
    }
   datav.push_back(new basis_t);
   *basis = datav.size() - 1;
   return 0;
}

int Basis_free(Basis_t basis) {
    delete datav[basis];
    datav[basis] = NULL;
    return 0;
}

int Basis_set_geom(Basis_t basis, Geom_t geom) {
    datav[basis]->geom = geom;
    
}

int Basis_get_geom(Basis_t basis, Geom_t *geom) {
    *geom = datav[basis]->geom;
}

int Basis_add_contr(Basis_t basis, int K, double *a, int KC, double **C, int *contr) {
    basis_contr_t bc;
    bc.K = K;
    bc.KC = KC;

    bc.a = (double*)malloc(K*(KC+1)*sizeof(double));
    
    for(int i = 0; i < K; ++i) {
	bc.a[i] = a[i];
    }

    for(int j = 0; j < KC; ++j) {
	bc.C[j] = (bc.a + K*(j+1));
	for(int i = 0; i < K; ++i) {
	    bc.C[j][i] = C[j][i];
	}
    }

    datav[basis]->contrs.push_back(bc);
    *contr = datav[basis]->contrs.size() - 1;

}			    

int Basis_add_shell(Basis_t basis, int type, int contr, int center, int *shell) {
    assert(contr >= 0 && contr < datav[basis]->contrs.size());
    assert(center >= 0 && center < Geom_size(datav[basis]->geom));
    basis_shell_t bs;
    bs.type = type;
    bs.contr = contr;
    bs.center = center;
    datav[basis]->shells.push_back(bs);
    *shell = datav[basis]->shells.size() - 1;
}

int Basis_add_func(Basis_t basis, int shell, int type, int *func) {
    basis_func_t bf;
    assert(shell >= 0 && shell < datav[basis]->shells.size());
    bf.shell = shell;
    bf.type = type;
    datav[basis]->funcs.push_back(bf);
    *func  = datav[basis]->funcs.size() - 1;
}

int Basis_index(Basis_t basis, int flags, int *index) {
    
    
}

int Basis_sort(Basis_t basis, int flags) {

}    

